#pragma once

#include <assert.h>
#include "ShmMessageNode.hpp"
#include "ShmMutex.hpp"
#include "ShmCond.hpp"
#include "ShmScopedLock.hpp"
#include "LOG_CYC.hpp"

#define MAX_SHM_MESSAGE_CONNECTIONS 128

class ShmMessagePool
{
public:
    ShmMessagePool()
        : _mutex()
        , _consumer()  // 初始化共享内存锁和条件变量
    {
        // 初始化节点池
        for (int i = 0; i < MAX_SHM_MESSAGE_CONNECTIONS; i++) {
            _nodes[i].SetNodePos(i);        // 记录自己当前位置
            _nodes[i].SetNext(freeIndex);       // 初始化下一个节点索引
            freeIndex = _nodes[i].GetNodePos();
            _nodes[i].SetFunctionType(ShmFunctionType::funcNULL);  // 初始化节点为未分配
            freeNum++;
        }
    }

    // 分配一个新的节点
    ShmMessageNode* New() {
        // 使用 ShmScopedLock 进行加锁
        ShmScopedLock pmtx(_mutex);

        // 如果没有空闲节点，则等待
        while (freeIndex == -1 || freeNum <= 0) {
            LOG_CYC(WARNING, "没有空闲节点，等待中...", nullptr);
            _consumer.Wait(_mutex);
        }

        // 分配节点
        assert(freeIndex >= 0);  // 确保有可用的空闲节点

        // 获取空闲节点并初始化数据
        int retPos = freeIndex;
        // 将后续空闲节点挂回链表
        freeIndex = _nodes[retPos].GetNext();

        // 初始化数据
        _nodes[retPos].SetFunctionType(ShmFunctionType::funcNULL);
        _nodes[retPos].SetExecuteSuccess(false);
        _nodes[retPos].SetNext(-1);
        _nodes[retPos].SetUse(true);



        freeNum--;

        //LOG_CYC(_DEBUG, "剩余节点数量：%d", freeNum);


        return &_nodes[retPos];
    }

    // 释放一个节点
    void Delete(ShmMessageNode* node) {
        // 使用 ShmScopedLock 进行加锁
        ShmScopedLock pmtx(_mutex);

        // 获取节点位置并验证
        assert(node != nullptr);  // 确保节点不为空
        assert(freeNum < MAX_SHM_MESSAGE_CONNECTIONS);  // 确保空闲节点数量不超过最大容量

        node->SetFunctionType(ShmFunctionType::funcNULL);
        node->SetUse(false);
        node->SetNext(freeIndex);
        freeIndex = node->GetNodePos();
        freeNum++;

        // 唤醒等待的线程
        _consumer.Signal();
    }

    // 根据位置查找已分配的节点，如果找到则返回节点指针，否则返回nullptr
    ShmMessageNode* FindAllocatedNodeByPos(int pos) {
        // ShmScopedLock pmtx(_mutex);

        assert(pos < MAX_SHM_MESSAGE_CONNECTIONS);
        if (pos >= 0) {
            // 加上消息节点内的锁
            ShmScopedLock pmtx(_nodes[pos].GetMutex());
            if (_nodes[pos].IsUse()) {
                return &_nodes[pos];
            }
        }
        return nullptr;
    }

private:
    ShmMessageNode _nodes[MAX_SHM_MESSAGE_CONNECTIONS];  // 节点数组
    int freeIndex = -1;  // 当前空闲节点的索引
    size_t freeNum = 0;  // 当前空闲节点的数量

    ShmMutex _mutex;  // 锁
    ShmCond _consumer;  // 消费者条件变量
};